@font-face{font-family:"SF Pro";src:url("fonts/SF-Pro-Display-Light.otf") format("opentype");font-weight:300}
@font-face{font-family:"SF Pro";src:url("fonts/SF-Pro-Text-Regular.otf") format("opentype");font-weight:400}
@font-face{font-family:"SF Pro";src:url("fonts/SF-Pro-Text-Medium.otf") format("opentype");font-weight:500}
@font-face{font-family:"SF Pro";src:url("fonts/SF-Pro-Text-Semibold.otf") format("opentype");font-weight:600}

:root{
  --ink:#3a3f47;
  --ink-2:#5a6068;
  --ink-3:#6b7280;
  --ink-4:#8e8e93;
  --blue:linear-gradient(135deg,#6b9bff,#3a6df0);
  --blue-solid:#3a6df0;
  --glass-alpha:.44;
  --glass-blur:30px;
  --ui-scale:.88;
  --radius:22px;
}

*{box-sizing:border-box}
html,body{margin:0;height:100%;overflow:hidden;background:#c9d2dc;font-family:"SF Pro",-apple-system,BlinkMacSystemFont,"Helvetica Neue",system-ui,sans-serif;-webkit-font-smoothing:antialiased;color:var(--ink)}
a{color:var(--ink);text-decoration:none}a:hover{color:var(--blue-solid)}
button{font-family:inherit;color:inherit}

/* stage: fixed 1672x941 design, scaled to viewport by JS */
.viewport{position:fixed;inset:0;display:flex;align-items:center;justify-content:center}
.stage{position:relative;width:1672px;height:941px;flex:none;transform-origin:center;overflow:hidden}

.scene-bg{position:absolute;inset:0;background:linear-gradient(180deg,#eef3f8 0%,#dbe4ee 45%,#c3ced9 60%,#e2e8ee 100%)}
.scene-glow{position:absolute;left:0;right:0;top:0;height:60%;background:radial-gradient(ellipse at 55% 20%,rgba(255,255,255,.9),transparent 60%)}

/* pixel streaming container — full screen, under the UI */
#pixel-stream{position:absolute;inset:0;overflow:hidden;transition:filter .5s ease,transform .5s ease}
/* Fake loading state while the environment switches (app.js blurStage) */
#pixel-stream.loading-blur{filter:blur(24px) saturate(1.05) brightness(.96);transform:scale(1.04)}
#pixel-stream iframe,#pixel-stream video{position:absolute;inset:0;width:100%;height:100%;border:0;display:block}
#pixel-stream .placeholder{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;pointer-events:none;font-size:12px;letter-spacing:.3em;color:var(--ink-4);text-align:center;line-height:22px}

/* UI overlay layer */
.ui{position:absolute;left:0;top:0;width:calc(1672px / var(--ui-scale));height:calc(941px / var(--ui-scale));transform:scale(var(--ui-scale));transform-origin:top left;pointer-events:none}
.ui>*{pointer-events:auto}
.ui .static{pointer-events:none}

.glass{background:rgba(255,255,255,var(--glass-alpha));backdrop-filter:blur(var(--glass-blur)) saturate(180%);-webkit-backdrop-filter:blur(var(--glass-blur)) saturate(180%);border:1px solid rgba(255,255,255,.7);box-shadow:0 8px 32px rgba(30,40,70,.10);border-radius:var(--radius)}

.brand{position:absolute;left:56px;top:34px}
.brand-row{display:flex;align-items:baseline;gap:14px}
.brand-name{font-size:38px;font-weight:300;letter-spacing:.42em}
.brand-num{font-size:30px}
.brand-tag{font-size:11px;letter-spacing:.42em;color:#4b5563;margin-top:2px}

.tagline{position:absolute;right:52px;top:45px;display:flex;align-items:center;gap:16px;font-size:11px;letter-spacing:.3em;color:var(--ink-3);opacity:.5}
.tagline .rule{width:64px;height:1px;background:var(--ink-3)}
/* top must clear .env-stack, which ends at 150 + its own height (~198) =
   ~348. 380 leaves a 32px gutter. Add a row to the environment grid and
   this number has to follow it down. */
.vertical-tag{position:absolute;right:46px;top:380px;font-size:13px;letter-spacing:.4em;line-height:20px;color:#4b5563;opacity:.5}
.vertical-tag .rule{width:32px;height:1px;background:#4b5563;margin-top:10px}
.footer-tag{position:absolute;left:56px;bottom:40px;font-size:11px;letter-spacing:.3em;color:var(--ink-3)}

/* ═══ left control column ═══════════════════════════════
   Grades / Configuration / Next step used to be three absolutely placed
   slots (top:114 / 242 / 748). The Configuration panel's height depends on
   how many swatches and rows the grade has, so it outgrew its 506px slot and
   slid under Next step. They are a flex stack now: a taller Configuration
   pushes Next step down instead of colliding with it, and the stack scrolls
   if it ever exceeds the column height.
   ═══════════════════════════════════════════════════════ */
.left-col{position:absolute;left:16px;top:104px;width:398px;
  /* leave the bottom-left corner to #streamStatus / .footer-tag */
  max-height:calc(100% - 222px);
  display:flex;flex-direction:column;gap:14px;
  /* The box scrolls, so it clips at its padding edge — 20px of inset keeps
     the panels' soft glass shadows inside it. The left/top offsets are pulled
     back by the same amount, so the panels still land on x=36 / y=114. */
  padding:10px 20px;overflow-y:auto;overflow-x:hidden;scrollbar-width:none;
  transition:transform .45s cubic-bezier(.2,.8,.2,1),opacity .35s ease,visibility .45s}
.left-col::-webkit-scrollbar{display:none}

.panel{position:relative;width:100%;flex:none;padding:14px 20px 18px}
/* the left column — fades out while a feature / the cinematic plays */
.panel,.brand,.footer-tag,#streamStatus{transition:opacity .45s ease,transform .45s ease,visibility .45s}

/* ═══ collapse handle ═══════════════════════════════════
   Sits just off the column's right edge and slides to the screen edge when
   the column is away, so it is always the thing you click to bring it back. */
.left-toggle{position:absolute;left:414px;top:114px;width:34px;height:36px;padding:0;
  border-radius:12px;cursor:pointer;display:flex;align-items:center;justify-content:center;
  background:rgba(255,255,255,.62);
  transition:left .45s cubic-bezier(.2,.8,.2,1),opacity .45s ease,visibility .45s,background .25s}
.left-toggle:hover{background:rgba(255,255,255,.92)}
.left-toggle svg{transition:transform .45s cubic-bezier(.2,.8,.2,1)}

body.left-collapsed .left-col{transform:translateX(-430px);opacity:0;visibility:hidden;pointer-events:none}
body.left-collapsed .left-toggle{left:26px}
body.left-collapsed .left-toggle svg{transform:rotate(180deg)}
.panel-head{display:flex;justify-content:space-between;align-items:center}
.panel-title{font-size:20px;font-weight:600}
.panel-sub{font-size:13px;color:var(--ink-4);margin-top:1px}
.divider{height:1px;background:rgba(60,60,67,.14);margin:12px 0}
.label{font-size:16px;font-weight:500}
.value{font-size:14px;color:var(--ink-2);margin-top:8px}

#config{padding:16px 20px 12px}

.seg2{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:12px}
.pill{height:42px;border-radius:21px;border:none;cursor:pointer;font-size:17px;font-weight:500;background:rgba(255,255,255,.85);box-shadow:0 1px 3px rgba(0,0,0,.06);transition:all .25s}
.pill.active{background:var(--blue);color:#fff;box-shadow:0 6px 16px rgba(58,109,240,.35)}

.swatches{display:flex;gap:8px;margin-top:8px}
.swatch{width:32px;height:32px;border-radius:50%;cursor:pointer;padding:0;border:none;box-shadow:0 1px 3px rgba(0,0,0,.15);transition:box-shadow .2s;background:radial-gradient(circle at 35% 30%,rgba(255,255,255,.55),transparent 55%),var(--c)}
.swatch.active{box-shadow:0 0 0 2px #fff,0 0 0 4px #7a4bb8}

.ambient{display:flex;align-items:center;gap:14px;margin-top:8px}
.amb{flex:1;margin:0;-webkit-appearance:none;appearance:none;height:12px;border-radius:6px;outline:none;background:linear-gradient(90deg,#ff3b30,#ffcc00,#34c759,#00c7be,#007aff,#af52de,#ff2d55)}
.amb::-webkit-slider-thumb{-webkit-appearance:none;width:24px;height:24px;border-radius:50%;background:#fff;border:3px solid rgba(255,255,255,.9);box-shadow:0 1px 6px rgba(0,0,0,.25);cursor:pointer}
.amb::-moz-range-thumb{width:24px;height:24px;border-radius:50%;background:#fff;border:3px solid #fff;box-shadow:0 1px 6px rgba(0,0,0,.25);cursor:pointer}
.amb-chip{width:64px;height:34px;border-radius:17px;background:rgba(255,255,255,.85);display:flex;align-items:center;justify-content:center;box-shadow:0 1px 3px rgba(0,0,0,.08)}

.row{display:flex;align-items:center;gap:14px;height:46px}
.row span{flex:1;font-size:16px}
.toggle{width:58px;height:32px;border-radius:16px;border:none;padding:0;cursor:pointer;position:relative;background:rgba(120,120,128,.32);transition:background .25s}
.toggle::after{content:"";position:absolute;top:3px;left:3px;width:26px;height:26px;border-radius:50%;background:#fff;box-shadow:0 2px 6px rgba(0,0,0,.25);transition:left .25s}
.toggle.on{background:var(--blue)}
.toggle.on::after{left:29px}

.btn{height:50px;border-radius:14px;border:none;cursor:pointer;font-size:17px;font-weight:500;display:flex;align-items:center;justify-content:center;gap:10px;background:rgba(255,255,255,.85);box-shadow:0 1px 3px rgba(0,0,0,.06)}
.btn:hover{background:#fff}
.btn.primary{background:var(--blue);color:#fff;box-shadow:0 6px 16px rgba(58,109,240,.35)}
.btn.primary:hover{filter:brightness(1.06)}

.view-switch{position:absolute;right:36px;top:88px;width:322px;height:46px;border-radius:23px;padding:4px;display:flex;background:rgba(255,255,255,.45)}
.view-switch button{flex:1;border:none;border-radius:19px;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:10px;font-size:17px;background:transparent;transition:all .25s}
.view-switch button.active{background:rgba(255,255,255,.95);font-weight:600;box-shadow:0 2px 8px rgba(0,0,0,.10)}

/* env tiles + Cinematic CTA stacked; the stack owns the position so the
   button always sits right under the box whatever height it grows to */
.env-stack{position:absolute;right:36px;top:150px;width:322px;display:flex;flex-direction:column;gap:10px;pointer-events:none}
.env-stack>*{pointer-events:auto}
#env{width:100%;padding:14px 12px 12px}
#env .panel-head{justify-content:flex-start;gap:10px;padding:0 6px;font-size:17px;font-weight:600}
.env-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:12px}
.env-grid button{height:80px;border-radius:14px;cursor:pointer;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;font-size:14px;background:rgba(255,255,255,.85);border:1.5px solid transparent;transition:all .25s}
.env-grid button.active{color:var(--blue-solid);background:rgba(58,109,240,.08);border-color:var(--blue-solid)}
/* Cinematic CTA — standalone button under the environment box */
.env-cta{width:100%;height:46px;border-radius:14px;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:10px;
  font-size:14px;font-weight:600;letter-spacing:.02em;color:#fff;border:1.5px solid transparent;
  background:linear-gradient(135deg,#3a6df0,#2b4fd0);box-shadow:0 6px 18px rgba(58,109,240,.28);transition:all .25s}
.env-cta:hover{filter:brightness(1.06);box-shadow:0 8px 22px rgba(58,109,240,.36)}
.env-cta:active{transform:translateY(1px)}
.env-cta.playing{background:linear-gradient(135deg,#2b4fd0,#1f3aa8)}

/* features bar — collapsed by default */
.features{position:absolute;left:432px;right:36px;bottom:70px;display:flex;flex-direction:column;gap:6px}
.features-head{display:flex;justify-content:space-between;align-items:center}
.features-toggle{height:36px;padding:0 18px;border-radius:18px;cursor:pointer;display:flex;align-items:center;gap:10px;font-size:17px;font-weight:500;background:rgba(255,255,255,.6);box-shadow:0 4px 16px rgba(30,40,70,.10)}
.features-toggle:hover{background:rgba(255,255,255,.85)}
.features-toggle svg{transition:transform .35s}
.features.open .features-toggle svg{transform:rotate(180deg)}
.explore{font-size:13px;color:var(--ink-2);display:flex;align-items:center;gap:10px;padding:6px 10px;border-radius:12px;background:rgba(255,255,255,.35);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}
.features-body{max-height:0;opacity:0;transform:translateY(24px);overflow:hidden;transition:max-height .45s cubic-bezier(.2,.8,.2,1),opacity .35s,transform .45s cubic-bezier(.2,.8,.2,1)}
.features.open .features-body{max-height:240px;opacity:1;transform:none}
.cards{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;padding:2px 0 8px}
.card{padding:16px 14px 12px;border-radius:18px;display:flex;flex-direction:column;min-height:160px}
.card-head{display:flex;align-items:center;gap:12px;font-size:17px;font-weight:600}
.specs{display:grid;grid-template-columns:1fr auto;row-gap:4px;font-size:13px;margin:10px 0 0 34px;color:var(--ink-3)}
.specs b{font-weight:400;color:var(--ink)}
.card p{font-size:13px;margin:10px 0 0 34px;color:var(--ink-3)}
.card p.big{font-size:14px;margin-top:4px;color:var(--ink)}
.card ul{font-size:13px;margin:10px 0 0 34px;padding-left:16px;color:var(--ink-3);line-height:22px}
.card-foot{display:flex;justify-content:space-between;align-items:center;margin-top:auto;padding-top:10px}
.card-foot small{font-size:11px;color:var(--ink-4)}
.more{width:30px;height:30px;border-radius:50%;border:none;background:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 4px rgba(0,0,0,.1);margin-left:auto}

/* ═══ stream status chip ═══════════════════════════════ */
#streamStatus{position:absolute;left:56px;bottom:78px;height:30px;padding:0 14px;display:flex;align-items:center;gap:9px;border-radius:15px;font-size:12px;letter-spacing:.12em;color:var(--ink-2);text-transform:uppercase}
.status-dot{width:8px;height:8px;border-radius:50%;background:#c6cacf;box-shadow:0 0 0 3px rgba(198,202,207,.28)}
.status-dot.live{background:#34c759;box-shadow:0 0 0 3px rgba(52,199,89,.22)}
.status-dot.error{background:#ff9500;box-shadow:0 0 0 3px rgba(255,149,0,.22)}

/* ambient chip acts as the on/off switch */
.amb-chip{cursor:pointer;transition:box-shadow .25s,background .25s}
.amb-chip.on{background:#fff}
.amb:not(.off){opacity:1}
.amb.off{opacity:.42}

/* ═══ overlays — summary + save dialog ═════════════════ */
#summaryOverlay,#saveDialog{position:fixed;inset:0;z-index:60;display:flex;align-items:center;justify-content:center;
  background:rgba(28,36,52,.38);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  opacity:0;visibility:hidden;transition:opacity .3s,visibility .3s}
#summaryOverlay.open,#saveDialog.open{opacity:1;visibility:visible}

.overlay-panel{width:min(520px,92vw);max-height:88vh;display:flex;flex-direction:column;
  background:rgba(255,255,255,.82);border-radius:26px;overflow:hidden;
  box-shadow:0 24px 70px rgba(20,28,45,.28);transform:translateY(14px) scale(.985);transition:transform .32s cubic-bezier(.2,.8,.2,1)}
#summaryOverlay.open .overlay-panel,#saveDialog.open .overlay-panel{transform:none}
.save-panel{width:min(440px,92vw)}

.overlay-header{display:flex;align-items:center;justify-content:space-between;padding:22px 26px 14px}
.overlay-title{font-size:21px;font-weight:600}
.overlay-close{width:34px;height:34px;border-radius:50%;border:none;cursor:pointer;background:rgba(255,255,255,.75);
  display:flex;align-items:center;justify-content:center;color:var(--ink-2);box-shadow:0 1px 4px rgba(0,0,0,.08)}
.overlay-close:hover{background:#fff}
.overlay-close svg{width:16px;height:16px}
.overlay-body{padding:4px 26px 8px;overflow-y:auto}
.overlay-footer{display:flex;gap:10px;padding:16px 26px 22px}
.overlay-footer .btn{height:48px}

.config-summary{display:flex;flex-direction:column}
.config-field{display:flex;justify-content:space-between;align-items:center;gap:20px;padding:13px 0;border-bottom:1px solid rgba(60,60,67,.13)}
.config-field:last-child{border-bottom:none}
.config-field-label{font-size:13px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4)}
.config-field-value{font-size:16px;font-weight:500;text-align:right}
.config-field-value.empty{color:var(--ink-4);font-weight:400}

.save-sub{font-size:14px;line-height:21px;color:var(--ink-2);margin:2px 0 18px}
.field-label{display:block;font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4);margin:12px 0 6px}
.field-input{width:100%;height:46px;padding:0 14px;border-radius:13px;border:1px solid rgba(60,60,67,.18);
  background:rgba(255,255,255,.85);font-family:inherit;font-size:16px;color:var(--ink);outline:none;transition:border-color .2s,box-shadow .2s}
.field-input:focus{border-color:var(--blue-solid);box-shadow:0 0 0 3px rgba(58,109,240,.16)}
.field-error{min-height:18px;font-size:13px;color:#d1344a;margin-top:8px}

.qr-frame{position:relative;width:212px;height:212px;margin:4px auto 0;border-radius:18px;background:#fff;
  display:flex;align-items:center;justify-content:center;box-shadow:0 6px 22px rgba(20,28,45,.14)}
.qr-img{width:188px;height:188px;image-rendering:pixelated;opacity:0;transition:opacity .3s}
.qr-frame.ready .qr-img{opacity:1}
.qr-loading{position:absolute;font-size:13px;color:var(--ink-4)}
.qr-frame.ready .qr-loading{display:none}
.save-code-label{margin-top:18px;font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4);text-align:center}
.save-code{margin-top:6px;font-size:22px;font-weight:600;letter-spacing:.14em;text-align:center;cursor:pointer}
.save-code:hover{color:var(--blue-solid)}
#shareUrl{margin-top:10px;font-size:12px;color:var(--ink-4);text-align:center;word-break:break-all;cursor:pointer}
#shareUrl:hover{color:var(--blue-solid)}

/* ═══ toast ════════════════════════════════════════════ */
/* ─── Boot loading overlay (driven by FAKE_LOAD_MS in app.js) ─── */
/* Fixed, not stage-scaled, so it also covers the letterboxing around the
   1672x941 stage. z-index sits above the summary/save overlays (60) and the
   toast (80) — nothing should be reachable until the bar finishes. */
#loadingOverlay{position:fixed;inset:0;z-index:90;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:34px;
  background:linear-gradient(180deg,#eef3f8 0%,#dbe4ee 45%,#c3ced9 60%,#e2e8ee 100%);
  transition:opacity .7s ease,visibility .7s}
#loadingOverlay::before{content:"";position:absolute;left:0;right:0;top:0;height:60%;
  background:radial-gradient(ellipse at 55% 20%,rgba(255,255,255,.9),transparent 60%);pointer-events:none}
#loadingOverlay.hidden{opacity:0;visibility:hidden;pointer-events:none}

.loading-brand{position:relative;text-align:center;animation:loadFadeUp .9s ease both}
/* The supplied artwork was ink on an opaque white field; the white is keyed
   to alpha in avatr-logo.png, so it needs no blend mode and stays correct on
   any backdrop. Sized by width — the source is square with ~15% padding. */
.loading-logo{display:block;margin:0 auto;width:200px;height:auto}
/* The artwork carries ~15% padding of its own, so the tagline sits tight. */
.loading-tag{font-size:11px;letter-spacing:.42em;color:#4b5563;margin-top:-6px}

.loading-bar-track{position:relative;width:260px;height:2px;background:rgba(58,63,71,.16);border-radius:2px;overflow:hidden}
/* Width is driven from JS (a CSS transition over the full duration), so the
   bar tracks the same clock as the percentage readout. */
.loading-bar-fill{height:100%;width:0;background:var(--blue);border-radius:2px}

.loading-status{position:relative;display:flex;align-items:center;gap:14px;font-size:11px;letter-spacing:.3em;color:var(--ink-3);text-transform:uppercase}
#loadingPct{min-width:42px;text-align:right;font-variant-numeric:tabular-nums;color:var(--ink-2)}

@keyframes loadFadeUp{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

#toast{position:fixed;left:50%;bottom:44px;z-index:80;transform:translate(-50%,16px);
  padding:13px 24px;border-radius:16px;font-size:15px;color:#fff;background:rgba(28,36,52,.88);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);box-shadow:0 10px 32px rgba(20,28,45,.28);
  opacity:0;visibility:hidden;transition:opacity .26s,transform .26s,visibility .26s;pointer-events:none}
#toast.show{opacity:1;visibility:visible;transform:translate(-50%,0)}

/* ═══ interior material swatches ═══════════════════════
   A miniature of the brochure upholstery close-up: smooth leather panel on
   the left, contrast stitch seam on the diagonal, perforated panel on the
   right. Colours come from the item's `mat` block in app.js (--l / --r /
   --st / --pf); .swatch.mat drops the flat --c fill those layers replace. */
.swatch.mat{position:relative;overflow:hidden;background:var(--r)}
.swatch.mat>span{position:absolute;inset:0;display:block}
.mat-l{background:var(--l);clip-path:polygon(0 0,47% 0,31% 100%,0 100%)}
.mat-r{clip-path:polygon(47% 0,100% 0,100% 100%,31% 100%);
  background:radial-gradient(circle at 1.1px 1.1px,var(--pf) .75px,transparent .85px) 0 0/3.6px 3.6px,var(--r)}
/* the seam: a dashed thread running the full height, tilted to match the split */
.swatch.mat>.mat-st{inset:-25% auto;left:47%;width:2.2px;height:150%;margin-left:-1.1px;
  transform:rotate(9deg);transform-origin:top center;
  background:repeating-linear-gradient(180deg,var(--st) 0 2.2px,transparent 2.2px 4.2px);
  box-shadow:0 0 0 .5px rgba(0,0,0,.28)}
/* keep the same soft top-left sheen the flat swatches have */
.swatch.mat::after{content:"";position:absolute;inset:0;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle at 35% 26%,rgba(255,255,255,.34),transparent 56%)}

/* ═══ feature cards ════════════════════════════════════
   Same look as the original static cards; now buttons that play a UE
   sequence ({ Features: "<tag>" }) when clicked. */
.feature-card{text-align:left;font:inherit;cursor:pointer;border:1px solid rgba(255,255,255,.7);
  transition:transform .25s,box-shadow .25s,border-color .25s,opacity .3s,filter .3s}
.feature-card:hover{transform:translateY(-3px);box-shadow:0 14px 34px rgba(30,40,70,.16)}
.feature-card .more{pointer-events:none}
.feature-card.active{border-color:var(--blue-solid);box-shadow:0 10px 28px rgba(58,109,240,.28)}

/* ─── Feature playback lock ───────────────────────────
   While a feature plays, body.ui-busy freezes every other control so the
   sequence can't be cut short. The card that's playing stays lit and counts
   itself out with a progress bar. */
body.ui-busy .pill,
body.ui-busy .swatch,
body.ui-busy .amb,
body.ui-busy .amb-chip,
body.ui-busy .toggle,
body.ui-busy .view-switch button,
body.ui-busy .env-grid button,
body.ui-busy .env-cta,
body.ui-busy .btn,
body.ui-busy .feature-card{pointer-events:none}

/* Left side of the UI clears out for the shot and comes back when it ends. */
body.ui-busy .panel,
body.ui-busy .left-col,
body.ui-busy .brand,
body.ui-busy .footer-tag,
body.ui-busy #streamStatus{opacity:0;visibility:hidden;transform:translateX(-28px);pointer-events:none}
body.ui-busy .left-toggle{opacity:0;visibility:hidden;pointer-events:none}
body.ui-busy .pill,
body.ui-busy .swatch,
body.ui-busy .amb,
body.ui-busy .amb-chip,
body.ui-busy .toggle,
body.ui-busy .view-switch button,
body.ui-busy .env-grid button,
body.ui-busy .env-cta,
body.ui-busy .btn,
body.ui-busy .feature-card:not(.active){opacity:.42;filter:saturate(.55)}
body.ui-busy .feature-card.active{position:relative;overflow:hidden}
body.ui-busy .feature-card.active::after{content:"";position:absolute;left:0;bottom:0;height:3px;width:0;
  background:var(--blue);animation:featureProgress var(--feature-ms,8500ms) linear forwards}
@keyframes featureProgress{from{width:0}to{width:100%}}


/* ═══ Compact layout ═════════════════════════════════════
   The wide layout is a fixed 1672x941 design scaled to fit, every panel in a
   hand-placed slot. That only holds while the viewport is roughly 16:9
   landscape — scale-to-fit on a portrait phone leaves a ~220px tall strip of
   UI stranded in the middle of the screen.

   Below the breakpoint the stage stops scaling and becomes a two-part column
   instead: stream on top, controls scrolling underneath. Panels return to
   normal flow, so they follow one another and CANNOT overlap by construction
   — there are no coordinates left to collide.

   fit() in app.js matches on the same query and skips the transform.
   Appended at the end of the file so these rules win on order alone.
   ═══════════════════════════════════════════════════════ */
@media (max-width: 900px), (orientation: portrait), (orientation: landscape) and (max-height: 600px){

  .stage{width:100%;height:100%;display:flex;flex-direction:column;transform:none!important}
  /* The scene gradient is the stream's backdrop, not the page's, so it stays
     pinned behind the video half only. */
  .scene-bg,.scene-glow{display:none}

  /* The stream is a flex item now rather than an inset:0 layer. */
  #pixel-stream{position:relative;inset:auto;flex:0 0 42vh;min-height:200px;width:100%;
    background:linear-gradient(180deg,#eef3f8 0%,#dbe4ee 45%,#c3ced9 60%,#e2e8ee 100%)}
  /* Feature / cinematic playback clears the controls away; give the car the
     room they free up rather than leaving a dead gap. */
  body.ui-busy #pixel-stream{flex:0 0 66vh}

  /* The UI stops being an overlay and becomes the scrolling half. It needs
     its own pointer-events back — the wide layout switches them off so clicks
     fall through to the stream, which would also swallow the scroll here. */
  .ui{position:relative;inset:auto;width:100%;height:auto;flex:1 1 auto;min-height:0;
    transform:none;overflow-y:auto;-webkit-overflow-scrolling:touch;pointer-events:auto;
    display:flex;flex-direction:column;gap:12px;padding:14px 14px 28px;
    /* The glass panels need something to sit on. In the wide layout that is
       the scene gradient showing through; here the scroll column covers it,
       so it carries its own. */
    background:linear-gradient(180deg,#dfe6ef 0%,#cdd7e3 100%);
    /* Meets the stream with a soft edge instead of a hard seam. */
    box-shadow:0 -18px 30px -18px rgba(30,40,70,.28) inset}

  /* Every hand-placed slot returns to normal flow. */
  .panel,.view-switch,.env-stack,.features,#streamStatus,.brand{
    position:static;left:auto;right:auto;top:auto;bottom:auto;width:auto}
  /* display:contents dissolves the wrapper so #grades/#config/#next are once
     again direct children of .ui and the order:N rules below still bite. The
     collapse handle is pointless here — nothing is overlapping to hide. */
  .left-col{display:contents}
  .left-toggle{display:none}
  body.left-collapsed .left-col{transform:none;opacity:1;visibility:visible;pointer-events:auto}

  /* Decoration only, and the vertical tag is the element that used to collide
     with the Cinematic button. Nothing here is a control. */
  .tagline,.vertical-tag,.footer-tag{display:none}

  /* DOM order is authored for the wide layout (config panel long before the
     view switch). Reading order on a phone wants the view switch up top and
     Summary/Save at the end. */
  #streamStatus{order:0;align-self:flex-start;flex:none}
  .brand{order:1}
  .view-switch{order:2;flex:none;height:46px}
  #grades{order:3}
  #config{order:4}
  .env-stack{order:5}
  .features{order:6}
  #next{order:7}

  .brand-row{gap:10px}
  .brand-name{font-size:30px}
  .brand-num{font-size:24px}
  .brand-tag{font-size:10px}

  /* Four cards across is unreadable narrow; let them wrap instead. */
  .cards{grid-template-columns:repeat(auto-fill,minmax(228px,1fr));gap:10px}
  /* The 240px cap is sized for the wide layout's single row. Here the grid is
     several rows tall, so lift it or the list is cut off mid-card. */
  .features.open .features-body{max-height:1600px}
  .features-head{flex-wrap:wrap;gap:8px}

  /* Dialogs: full-bleed-ish sheets rather than centred cards. */
  .overlay-panel{width:min(520px,94vw);max-height:90vh}
}

/* ═══════════════════════════════════════════════════════
   PHONE HELD SIDEWAYS — stream beside the controls
   ───────────────────────────────────────────────────────
   A landscape phone is only ~390-430px tall. Keeping the stacked split
   gives the car ~190px and the controls ~190px, and both are useless. The
   screen is wide, though, so the split turns 90°: the car takes the full
   height on the left, the controls become one scrolling column on the right.

   Keyed on HEIGHT, not width — that is what is actually scarce here, and a
   932px-wide phone in landscape would slip past a max-width test.
   ═══════════════════════════════════════════════════════ */
@media (orientation: landscape) and (max-height: 600px){

  .stage{flex-direction:row}

  /* The car takes the full height and whatever width the column leaves. */
  #pixel-stream{flex:1 1 auto;width:auto;height:100%;min-height:0;min-width:0}
  /* The stacked layout grows the stream while a feature plays. Here the split
     is horizontal and the column is already narrow, so leave it alone. */
  body.ui-busy #pixel-stream{flex:1 1 auto}

  /* The control column: a fixed share of the width, scrolling on its own. */
  .ui{flex:0 0 clamp(248px,38vw,360px);width:auto;height:100%;min-height:0;
      padding:8px 9px 16px;gap:8px;
      box-shadow:-18px 0 30px -18px rgba(30,40,70,.28) inset}

  /* The wordmark fits again now that it is not competing with the car for
     vertical space — centred over the column, with the live chip above it. */
  .brand{display:block;order:1;text-align:center}
  .brand-row{justify-content:center;gap:8px}
  .brand-name{font-size:18px;letter-spacing:.28em}
  .brand-num{font-size:15px}
  .brand-tag{font-size:8px;letter-spacing:.26em;margin-top:1px}
  #streamStatus{height:23px;padding:0 10px;font-size:10px;gap:7px}
  .status-dot{width:7px;height:7px}

  /* Everything tightens: the column is narrow and the viewport is short. */
  .panel{padding:9px 12px 11px;border-radius:16px}
  .panel-title{font-size:15px}
  .panel-sub{font-size:10px}
  .divider{margin:7px 0}
  .label{font-size:12.5px}
  .value{font-size:11.5px;margin-top:5px}
  .seg2{gap:6px;margin-top:7px}
  .pill{height:31px;font-size:13px;border-radius:16px}
  .row{height:33px;gap:9px}
  .row span{font-size:12.5px}
  .row>svg{width:18px;height:18px}
  .toggle{width:44px;height:25px}
  .toggle::after{top:2.5px;left:2.5px;width:20px;height:20px}
  .toggle.on::after{left:21.5px}
  .btn{height:37px;font-size:13.5px;gap:7px;border-radius:12px}
  .btn svg{width:15px;height:16px}
  .view-switch{height:35px;padding:3px;border-radius:18px}
  .view-switch button{font-size:13px;gap:5px;border-radius:15px}
  .view-switch button svg{width:16px;height:16px}
  .ambient{gap:9px;margin-top:6px}
  .amb{height:9px}
  .amb::-webkit-slider-thumb{width:19px;height:19px}
  .amb-chip{width:44px;height:26px}
  .amb-chip svg{width:15px;height:15px}

  /* Shrink the dots so all seven exterior colours stay on one line. */
  .swatches{gap:6px;margin-top:6px;flex-wrap:wrap}
  .swatch{width:26px;height:26px}

  #env{padding:9px 9px 9px;border-radius:16px}
  #env .panel-head{font-size:13.5px;gap:8px}
  #env .panel-head svg{width:17px;height:17px}
  .env-grid{gap:6px;margin-top:8px}
  .env-grid button{height:54px;font-size:10px;gap:4px;border-radius:12px}
  .env-grid button svg{width:20px;height:20px}
  .env-cta{height:36px;font-size:13px}

  /* One card at a time, and the open list may scroll rather than push the
     rest of the column off the bottom. */
  .cards{grid-template-columns:1fr}
  .features.open .features-body{max-height:70vh}

  /* A short viewport makes a centred dialog taller than the screen. */
  .overlay-panel{max-height:94vh}
  .overlay-header{padding:14px 18px 8px}
  .overlay-body{padding:4px 18px 6px}
  .overlay-footer{padding:10px 18px 14px}
  .qr-frame{width:150px;height:150px}
  .qr-img{width:132px;height:132px}
}
